//
//  SleepDataChartViewModel.swift
//  MoyoungHome
//
//  Created by 李然 on 2022/9/26.
//

import UIKit
import RxCocoa
import RxSwift
import SwiftDate
import Charts
import MYModule

public class SleepDataChartViewModel: ViewModel,ViewModelType {
    
    public let date:Date
    public let chartType:DataChartType
    
    public let YMax: Double = 720
    public let YMin: Double
    
    public let defaultValue:SleepModel
    public let dataSource:[SleepModel]
    
    public init(date:Date,
         defaultValue:SleepModel,
         dataSource:[SleepModel],
         chartType:DataChartType) {
        
        self.date = date
        self.chartType = chartType
        self.defaultValue = defaultValue
        self.dataSource = dataSource
        
        switch chartType {
        case .day:
            YMin = 0
            break
        case .week:
            YMin = YMax * 0.05
            break
        case .month:
            YMin = YMax * 0.05
            break
        case .custom:
            YMin = YMax * 0.05
            break
        }
        
        super.init()
    }
    
    public struct Input {
        public let selectIndex: PublishSubject<Int>
        
        public init(selectIndex: PublishSubject<Int>) {
            self.selectIndex = selectIndex
        }
    }
     
    public struct Output {
        public let hourString:Driver<String>
        public let minuteString:Driver<String>
        public let timeString:Driver<String>
        
    }
    
    public var sliderEnd: PublishSubject<Bool> = PublishSubject<Bool>()
    
    public func transform(input: Input) -> Output {
        
        let timeString = BehaviorRelay<String>(value: "--")
        let hourString = BehaviorRelay<String>(value: "--")
        let minuteString = BehaviorRelay<String>(value: "--")
        
        input.selectIndex
            .asObservable()
            .subscribe(onNext:{ [weak self] selectIndex in
                guard let `self` = self else {return }
                
                
                switch self.chartType {
                case .month:
                    let selectDate = self.date.dateAtStartOf(.month) + selectIndex.days
                    let dateString = self.getSelectedTimeString(with: selectDate)
                    timeString.accept(dateString)
                    
                    if self.dataSource.count > selectIndex {
                        let record = self.dataSource[selectIndex]
                        
                        let totalHours = record.total/60
                        let totalMinutes = record.total - totalHours * 60
                        if totalHours == 0 && totalMinutes == 0 {
                            hourString.accept("--")
                            minuteString.accept("--")
                        } else {
                            hourString.accept(String(totalHours.leadingZero))
                            minuteString.accept(String(totalMinutes.leadingZero))
                        }
                    }
                    
                case .week:
                    let selectDate = self.date.dateAtStartOf(.weekOfMonth) + selectIndex.days
                    let dateString = self.getSelectedTimeString(with: selectDate)
                    timeString.accept(dateString)
                    
                    if self.dataSource.count > selectIndex {
                        let record = self.dataSource[selectIndex]
                        let totalHours = record.total/60
                        let totalMinutes = record.total - totalHours * 60
                        
                        if totalHours == 0 && totalMinutes == 0 {
                            hourString.accept("--")
                            minuteString.accept("--")
                        } else {
                            hourString.accept(String(totalHours.leadingZero))
                            minuteString.accept(String(totalMinutes.leadingZero))
                        }
                       
                    }
                    
                case .day:
                    if self.defaultValue.detail.count > selectIndex {
                        
                        let record = self.defaultValue.detail[selectIndex]
                       
                        let dateString = " \(record.start)-\(record.end)"
                        timeString.accept(dateString)
                        
                        let total = record.total
                        let totalHours = total/60
                        let totalMinutes = total - totalHours * 60
                        
                        if totalHours == 0 && totalMinutes == 0 {
                            hourString.accept("--")
                            minuteString.accept("--")
                        } else {
                            hourString.accept(String(totalHours.leadingZero))
                            minuteString.accept(String(totalMinutes.leadingZero))
                        }
                
                    }
                default :
                    break
                }
        }).disposed(by: rx.disposeBag)
        
        
        let timeTuple = defaultHourAndMinute()
        hourString.accept(timeTuple.hour.normalTitle)
        minuteString.accept(timeTuple.minutes.normalTitle)

        timeString.accept(self.getDefaultTimeString())
        
       
        sliderEnd.subscribe(onNext: {[weak self] _ in
            
            guard let self = self else { return }
            
            let timeTuple = self.defaultHourAndMinute()
            hourString.accept(timeTuple.hour.normalTitle)
            minuteString.accept(timeTuple.minutes.normalTitle)

            timeString.accept(self.getDefaultTimeString())
            
            
        }).disposed(by: rx.disposeBag)
        

        return Output(hourString: hourString.asDriver(onErrorJustReturn: "--"),
                      minuteString: minuteString.asDriver(onErrorJustReturn: "--"),
                      timeString: timeString.asDriver(onErrorJustReturn: "--"))
    }
    
    private func getDefaultTimeString() -> String{
        return getTimeString(with: self.date)
    }
    
    private func defaultHourAndMinute() ->(hour: Int, minutes: Int) {
        
        var hour = 0
        var minute = 0
        
        switch chartType {
            
        case .week, .month:
            
            let models = dataSource.filter({ !$0.isEmpty })
            var minutesAvg = 0
            models.forEach {(
                minutesAvg += $0.total
            )}
            if !models.isEmpty {
                minutesAvg = minutesAvg/models.count
            }
            
            hour = minutesAvg/60
            minute = minutesAvg - hour * 60
            
            break
        default:
            
            hour = self.defaultValue.total/60
            minute = self.defaultValue.total - hour * 60
            break
        }
        
        return (hour, minute)
        
    }
    
    private func getDefaultHoursString() -> String {
        
        
        guard self.defaultValue.detail.count > 0 else {
            return "--"
        }
        return String((self.defaultValue.total/60).leadingZero)
    }
    
    private func getDefaultMinuteString() -> String{
        guard self.defaultValue.detail.count > 0 else {
            return "--"
        }
        let totalHours = self.defaultValue.total/60
        return String((self.defaultValue.total - totalHours * 60).leadingZero)
    }
    
    private func getTimeString(with date:Date) -> String{
        
        switch chartType {
            
        case .day:
            return date.localString
        case .week:
            return date.localweekRangeString
        case .month:
            return date.localMonthRangeString
        case .custom:
            return date.localString
        }
     
    }
    
    private func getSelectedTimeString(with date:Date) -> String{
        
        switch chartType {
            
        case .day:
            return date.localString
        case .week:
            return date.localString
        case .month:
            return date.localString
        case .custom:
            return date.localString
        }
     
    }
    
    /// 获取x轴的数量
    open func getBarCount() -> Int{
        switch self.chartType{
        case .day,.custom: return dataSource.count
        case .week: return 7
        case .month: return self.date.monthDays
        }
    }
    
    /// 获取x轴的格式器
    open func getXAxisValueFotmatter() ->IAxisValueFormatter{
        switch chartType {
        case .day,.custom: return DayAxisValueFormatter()
        case .week: return WeekAxisValueFormatter()
        case .month: return MonthAxisValueFormatter(date: date)
        }
    }
    
    open func getMaxValue() -> Double{
        return Double( self.dataSource.map{$0.total}.max() ?? 0)
    }
    
}
